package com.file.parser;

import com.file.bo.ResponseData;
import com.file.bo.mail.ABC;
import com.file.bo.mail.ABCTran;
import com.file.constant.EfpConstants;
import com.file.constant.ErrorCode;
import com.file.parser.traprange.PDFTableExtractor;
import com.file.util.JsonUtils;
import com.google.common.base.Strings;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Slf4j
public class ABCPdfParser extends BasePdfParser {

	public ResponseData<String> parseABCPdfToJson(String filePath) {
		log.info("parseABCPdfToJson started, filePath:{}", filePath);
		String json = null;

		try {
			ABC abc = parseABCPdf(filePath);
			json = JsonUtils.convertObjectToJson(abc);
		} catch (Exception e) {
			log.error("[OnError]parseABCPdfToJson failed, filePath:{}", filePath, e);
			return new ResponseData<String>(json, ErrorCode.FILE_PARSE_EXCEPTION.getCode(),
					ErrorCode.FILE_PARSE_EXCEPTION.getMsg());
		}

		log.info("parseABCPdfToJson completed, filePath:{}", filePath);
		return new ResponseData<String>(json, ErrorCode.SUCCESS.getCode(), ErrorCode.SUCCESS.getMsg());
	}

	private ABC parseABCPdf(String filePath) {
		ABC abc = parseABCHeader(filePath);

		List<ABCTran> abcTrans = parseAbcTrans(filePath);
		try {
			parseConterparty(filePath, abcTrans);
		} catch (Exception e) {
			log.warn("parseConterparty failed", e);
		}
		abc.setAbcTrans(abcTrans);
		log.info("abc = " + abc);
		return abc;
	}

	private ABC parseABCHeader(String filePath) {
		ABC abc = new ABC();
		String pdfHeaderText = parsePdfHeaderText(filePath);
		String name = pdfHeaderText.substring(pdfHeaderText.indexOf("⼾名：") + 3, pdfHeaderText.indexOf("账⼾：")).trim();
		String account = pdfHeaderText.substring(pdfHeaderText.indexOf("账⼾：") + 3, pdfHeaderText.indexOf("币种：")).trim();
		String currency = pdfHeaderText.substring(pdfHeaderText.indexOf("币种：") + 3, pdfHeaderText.indexOf("钞汇标识："))
				.trim();
		String cashExchangeIndicator = pdfHeaderText
				.substring(pdfHeaderText.indexOf("钞汇标识：") + 5, pdfHeaderText.indexOf("起⽌⽇期：")).trim();
		String transDetailPeriod = pdfHeaderText
				.substring(pdfHeaderText.indexOf("起⽌⽇期：") + 5, pdfHeaderText.indexOf("电⼦流⽔号：")).trim();
		String serialNo = pdfHeaderText.substring(pdfHeaderText.indexOf("电⼦流⽔号：") + 6, pdfHeaderText.indexOf("交易⽇期"))
				.trim();

		abc.setName(name);
		abc.setAccount(account);
		abc.setCurrency(currency);
		abc.setCashExchangeIndicator(cashExchangeIndicator);
		abc.setTransDetailPeriod(transDetailPeriod);
		abc.setSerialNo(serialNo);
		return abc;
	}

	private List<ABCTran> parseAbcTrans(String filePath) {
		List<ABCTran> abcTrans = new ArrayList<>();

		String transText = parseTransToText(filePath);
		if (Strings.isNullOrEmpty(transText)) {
			return abcTrans;
		}

		List<List<String>> tranFieldsList = parseTransTextToTranFieldsList(transText);

		for (List<String> strings : tranFieldsList) {
			ABCTran abcTran = new ABCTran();
			abcTran.setTranDate(strings.get(0));
			abcTran.setTranTime(strings.get(1));
			abcTran.setTranSummary(strings.get(2));
			abcTran.setTranAmt(strings.get(3));
			abcTran.setBalance(strings.get(4));
			abcTran.setCounterPartyInfo(strings.get(5));
			abcTran.setTranChannel(strings.get(6));
			abcTran.setTranComment(strings.get(7));
			abcTrans.add(abcTran);
		}

		return abcTrans;
	}

	private String parseTransToText(String filePath) {
		PDFTableExtractor extractor = (new PDFTableExtractor()).setSource(filePath);
		int pdfPageNumber = getPdfPageNumber(filePath);

		// 处理 header
		// 处理第一页的header
		int[] skipLinesIndexesInFirstPage = new int[EfpConstants.ABC_PDF_HEADER_LINE_NUMBER];
		for (int i = 0; i < EfpConstants.ABC_PDF_HEADER_LINE_NUMBER; i++) {
			skipLinesIndexesInFirstPage[i] = i;
		}
		extractor.exceptLine(0, skipLinesIndexesInFirstPage);
		// 处理从第二页到最后一页的header
		for (int i = 1; i < pdfPageNumber; i++) {
			int[] skipLinesInNoneFirstPage = { 0 };
			extractor.exceptLine(i, skipLinesInNoneFirstPage);
		}

		// 处理footer
		// 处理最后一页Footer
		int lineNumberInLastPdf = getLineNumberInLastPage(filePath, pdfPageNumber);
		if (lineNumberInLastPdf == EfpConstants.ABC_PDF_FOOTER_LINE_NUMBER) {
			// 因为农行Footer只有一行，所以如果最后一页只有一行，就可以去掉最后一页
			extractor.exceptPage(pdfPageNumber - 1);
		} else {
			// 否则最后一页要去掉最后一行
			int[] skipLinesIndexesInLastPage = new int[EfpConstants.ABC_PDF_FOOTER_LINE_NUMBER];
			for (int j = 0; j < EfpConstants.ABC_PDF_FOOTER_LINE_NUMBER; j++) {
				skipLinesIndexesInLastPage[j] = -(j + 1);
			}
			extractor.exceptLine(pdfPageNumber - 1, skipLinesIndexesInLastPage);
		}

		return extractPdfToText(extractor);
	}

	private void parseConterparty(String filePath, List<ABCTran> abcTrans) {
		String pdfText = getPdfTextByStripper(filePath);
		pdfText = pdfText.replace(System.getProperty("line.separator", "\n"), " ");
		log.info("pdfText = " + pdfText);

		// 此处一行的格式 20210427 162949 代付 +10.00 10.00 ⽀付宝（中国）⽹络技术有限公司 电⼦商务
		// NG2021042740533382830236200311306余额宝提现
		Pattern pattern1 = Pattern
				.compile("\\d{8}(\\s|\\s\\d{6}\\s)\\S{1,20}\\s\\-?\\+?\\d+(\\.\\d{1,2})?\\s\\d+(\\.\\d{1,2})?\\s");
		Matcher matcher1 = pattern1.matcher(pdfText);

		// 每行交易记录的第一个字所在的index
		int tranIndex = 0;
		Map<Integer, Integer> tranTextStartIndexMap = new HashMap<>();

		while (matcher1.find()) {
			// log.info(
			// "Match \"" + matcher1.group() + "\" at positions " + matcher1.start() + "-" +
			// (matcher1.end() - 1));
			tranTextStartIndexMap.put(tranIndex, matcher1.start());
			tranIndex++;
		}
		// log.info(String.valueOf(abcTrans.size()));

		// 找出每行交易记录的文本
		List<String> tranTextList = new ArrayList<>();
		for (int i = 1; i < tranTextStartIndexMap.size(); i++) {
			String tranText = pdfText.substring(tranTextStartIndexMap.get(i - 1), tranTextStartIndexMap.get(i));
			// if (tranText.contains("交易⽇期")) {
			// tranText = tranText.substring(0, tranText.indexOf("交易⽇期")).trim();
			// }
			if (tranText.contains("该交易明细因不可预测的⾮⼈控技术原因可能导致数据缺失")) {
				tranText = tranText.substring(0, tranText.indexOf("该交易明细因不可预测的⾮⼈控技术原因可能导致数据缺失")).trim();
			}
			// log.info(tranText);
			tranTextList.add(tranText);
		}

		String lastTranText = pdfText.substring(tranTextStartIndexMap.get(tranTextStartIndexMap.size() - 1));
		if (lastTranText.contains("交易⽇期")) {
			lastTranText = lastTranText.substring(0, lastTranText.indexOf("交易⽇期")).trim();
		}
		// log.info(lastTranText);
		tranTextList.add(lastTranText);

		// log.info(String.valueOf(tranTextList.size()));

		// 找出每行交易里的对手信息的值
		for (int i = 0; i < tranTextList.size(); i++) {
			ABCTran abcTran = abcTrans.get(i);
			String[] strArr = { abcTran.getTranDate(), abcTran.getTranTime(), abcTran.getTranSummary(),
					abcTran.getTranAmt(), abcTran.getBalance(), abcTran.getCounterPartyInfo(),
					abcTran.getTranChannel() };
			String str = String.join(StringUtils.SPACE, strArr).replaceAll("\\s+", StringUtils.SPACE);
			String tranComment = tranTextList.get(i).substring(str.length()).trim();
			abcTran.setTranComment(tranComment);
		}
	}

	public static void main(String[] args) throws IOException {
		ABCPdfParser abcPdfParser = new ABCPdfParser();
		ABC abc = abcPdfParser.parseABCPdf("E:\\data\\files\\ABC\\农业银行交易明细.pdf");
		String json = JsonUtils.convertObjectToJson(abc);
		System.out.println(json);
		File file = new File("E:\\data\\files\\ABC\\农业银行交易明细.json");
		OutputStream output = new FileOutputStream(file);
		IOUtils.write(json, output, Charset.forName("Unicode"));
	}

}
